package com.demo.k8s.controller;

import lombok.extern.slf4j.Slf4j;
import org.jose4j.json.JsonUtil;
import org.jose4j.jwk.JsonWebKey;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.NumericDate;
import org.jose4j.lang.JoseException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.security.PrivateKey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 鉴权controller
 */
@Slf4j
@RestController
public class OauthController {

    /**
     * jwk必须提前生成，因为生成jwt和验证jwt必须使用同一个jwk
     */
    private final String jwk = "{\n" +
            "    \"kty\":\"RSA\",\n" +
            "    \"kid\":\"authServer\",\n" +
            "    \"n\":\"uHl3KjsJ4oNCYgbV5BmlQTdLgoA32-j9eCWE6ZGytZp1Y1mw7hBy1K1F5whZDzS19cNG6a59MtBxvEt_zzkwBGwgc5F2P8-e4q3j2H8Bomk-AlqyFsTpQ7vDDKl-cqrnOvPlK8kv4wCFzPQ5sFT_fzxBXeFma8tEA5gH4r1A-2gZd7UpzQn3U6aWldNpQ0c04rqUJIXsnsjSV4DmeVoVGjYOhhOX_BlbTIDAqqHpBITlTstTNqGktwT4dIuNkLap8F5wFyuXoYoFhZDB5SBei1k8BocwUkCcvlFZevw86R_4X-fwZDXeDC3_CsgjRQw2oP4VYYE2kHQRROk5XpXyQQ\",\n" +
            "    \"e\":\"AQAB\",\n" +
            "    \"d\":\"UMVmRshY2KPuMeuaRWhxMe_bEQXA73nBWZTb8ETKAbfihCCmVmY_UR2ZCMJf9Ed5EGVzLCgpS1F3KyHHkV0RyC3ru45KP0BR6iCHLajWd10rOG6roUqQdAbHLUkdQ2nPGsHlatmJLRRygT3B8JIW2Ifyev-RD8uNOSGc-ksxI6I9lMolk3iyGcx-mMMHKEMdLzBkYQ6nSxlVmh6A6RQIdloiODAKPdbm-dZY0RsNXdZOqWP9G2TbI5QugdZAmllY9fP69PxSIDPpRZ406lA7J3eRbKbMdEyWXGLj_MH3tQ00oRhbgyYR0mp4SiinyZdSBojdPvfYyIzT0tmYXbE-UQ\",\n" +
            "    \"p\":\"-vsNFrm3n6XsYJIKJnwqTFPfjXerFF_Jy6UV-wHPB7o7IKJIL2FGowi6rnUoeQuteaeJMZ4yzOm1hUQNSgv6XTQ8s-m_SmurUdk0cuYP9vc-ipENMhhF39llUOUNNgV-ZFj6MLS7Na7_tjhxm6BGkvzRRrc4_XD1fcSPpcUtPU0\",\n" +
            "    \"q\":\"vCnr-N4lyKn3VkW4Ae8xxYntAa8jca3EjtDbSOVQEWUhpurHGIJnZ94FqDo0Ma8HUvYplX_BtZEPqTw1jN-5ukTzfLzQgYVcAf-jQX5cyRwxqrQTfC2a5eyOdmAxBfzqTK4JLTxliDKtNACa3k3XPp3S71Y910BmbC273uuR3sU\",\n" +
            "    \"dp\":\"Kl3sxLRPCfUhZN_iNMLrBP13lFLqH0NYNjdE8Z1JjH1kc8rRMqZSHT1g_ggq79wHyax9XVHeM3cUPE3TjHdfKRKjWJ-RugdY4TUwRGEPutnbxdpchuNQEEyLbM9tnnvo7RmUClrH63UCF4mJrAKvRyrETRKq3SWPW06uDQau71U\",\n" +
            "    \"dq\":\"DJzexXLWo4nJG45W1EJdWrlxGqDLxm34c_5KBKviXxghVlf8eocbOVonlOw53W63FfeMOAo1SN9tZlGz4TqJ75N5os3hSB1RWozxO42l2JE8Pw4NFFDWRj1CG2s9PgKDDhrIYLDguW10ML0tpGMhX4AiyIpGYOxfMTcrlbjCsWU\",\n" +
            "    \"qi\":\"QpRZCNLTSU7NkDqObA523xQsQ9icly-vu3rnrHuMIUdAJAcBqV4UqpbEW5ASxv9fgljlZpeFR7nsfXzG4J-Uj2H_dkh1kyiz5mMyBYwrmtnB7lgAR1-4Wh_du8IkpfLwHYIsohqxy6Nm571dzY4ZzrCeoeM49JKdsSFVc9BiS3Q\"\n" +
            "}";

    /**
     * istio的RequestAuthentication获取jwks
     * @return 返回jwks
     * @throws JoseException jose异常
     */
    @GetMapping("/k8s/jwks")
    public Map<String, Object> jwks() throws JoseException {
        RsaJsonWebKey rsaJsonWebKey = new RsaJsonWebKey(JsonUtil.parseJson(jwk));
        Map<String, Object> params = rsaJsonWebKey.toParams(JsonWebKey.OutputControlLevel.PUBLIC_ONLY);

        Map<String, Object> map = new HashMap<>();
        map.put("keys", List.of(params));
        log.info("jwks:{}", map);
        return map;
    }

    /**
     * 获取token
     * @param name 请求参数
     * @return 返回token
     * @throws JoseException jose异常
     */
    @GetMapping("/k8s/token")
    public String genToken(@RequestParam("name") String name) throws JoseException {
        RsaJsonWebKey rsaJsonWebKey = new RsaJsonWebKey(JsonUtil.parseJson(jwk));

        //过期时间一分钟
        NumericDate date = NumericDate.now();
        date.addSeconds(60 * 60);

        JwtClaims claims = new JwtClaims();
        // issuer对应istio配置kind=RequestAuthentication的issuer
        claims.setIssuer("testing@secure.istio.io");
        claims.setSubject("testing@secure.istio.io");
        claims.setNotBeforeMinutesInThePast(1);
        claims.setExpirationTime(date);
        claims.setStringClaim("name", name);

        JsonWebSignature jws = new JsonWebSignature();
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
        //必须设置，对应jwk的kid
        jws.setKeyIdHeaderValue("authServer");
        jws.setPayload(claims.toJson());

        PrivateKey privateKey = rsaJsonWebKey.getPrivateKey();
        jws.setKey(privateKey);
        String jwtResult = jws.getCompactSerialization();
        log.info("jwt:{}", jwtResult);
        return jwtResult;
    }
}
